package Socketserver.Socket;

import Public.SocketResult;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class SocketServer implements SocketServerAbstract {
    public ServerSocket server;
    public Socket clientSocket;
    public DataInputStream dis; // 输入流（连接后初始化，复用）
    public DataOutputStream dos; // 输出流（连接后初始化，复用）
    public String baseTxtPath = "D:\\a_E\\桌面\\IdeaProjects\\IdeaProjects\\WHAT_JAVA_HOMEWORK_FOR_CLASS\\src\\aTXT_pagage\\";
    private static final int TIMEOUT_MS = 5000; // 5秒超时设置


    // 1. 创建ServerSocket连接
    @Override
    public boolean ServerSocket_CREATE_Socket() throws IOException {
        if (server == null || server.isClosed()) {
            server = new ServerSocket(8080);
            System.out.println("ServerSocket创建成功，监听端口8080");
            return true;
        }
        return false;
    }


    // 2. 接收字符串（添加超时处理）
    @Override
    public SocketResult ServerSocket_INPUT_STRING() throws IOException {
        if (dis == null) {
            return new SocketResult(false, "输入流未初始化", null);
        }
        try {
            // 读取普通字符串或长文本标识
            String data = dis.readUTF();

            // 长文本处理逻辑
            if ("LONG_TEXT".equals(data)) {
                int totalBlocks = dis.readInt();
                int totalLength = dis.readInt();
                byte[] allBytes = new byte[totalLength];
                int currentPos = 0;
                for (int i = 0; i < totalBlocks; i++) {
                    int bytesToRead = Math.min(64535, totalLength - currentPos);
                    dis.readFully(allBytes, currentPos, bytesToRead);
                    currentPos += bytesToRead;
                }
                data = new String(allBytes, "UTF-8");
                System.out.println("收到长文本（总长度：" + totalLength + "字节）");
                dos.writeUTF("SUCCESS");
                dos.flush();
                String testStrForReceive10 = "服务器发送的测试字符串（供测试10）";
                dos.writeUTF(testStrForReceive10);
                dos.flush();
                System.out.println("已发送测试10的字符串：" + testStrForReceive10);

            } else {
                // 普通字符串处理
                System.out.println("收到客户端字符串：" + data);
                dos.writeUTF("SUCCESS");
                dos.flush();
                System.out.println("已发送普通字符串响应（供测试4）");
            }

            return new SocketResult(true, "字符串接收成功", data);
        } catch (SocketTimeoutException e) {
            // 5秒未收到数据，断开连接
            ServerSocket_CLOSE();
            return new SocketResult(false, "接收字符串超时（5秒），已断开连接", null);
        } catch (IOException e) {
            return new SocketResult(false, "字符串接收失败：" + e.getMessage(), null);
        }
    }


    // 3. 接收文件（添加超时处理）
    @Override
    public SocketResult ServerSocket_INPUT_FILE() throws IOException {
        if (dis == null) {
            return new SocketResult(false, "输入流未初始化", null);
        }
        try {
            String fileName = dis.readUTF();
            long fileSize = dis.readLong();
            Files.createDirectories(Paths.get(baseTxtPath));
            File saveFile = new File(baseTxtPath + fileName);
            try (FileOutputStream fos = new FileOutputStream(saveFile)) {
                byte[] buffer = new byte[1024 * 128];
                int bytesRead;
                long totalRead = 0;
                while (totalRead < fileSize && (bytesRead = dis.read(buffer)) != -1) {
                    fos.write(buffer, 0, bytesRead);
                    totalRead += bytesRead;
                }
            }
            dos.writeUTF("SUCCESS");
            dos.flush();
            return new SocketResult(true, "文件接收成功", saveFile.getAbsolutePath());
        } catch (SocketTimeoutException e) {
            // 5秒未收到数据，断开连接
            ServerSocket_CLOSE();
            return new SocketResult(false, "接收文件超时（5秒），已断开连接", null);
        } catch (IOException e) {
            return new SocketResult(false, "文件接收失败：" + e.getMessage(), null);
        }
    }


    // 4. 统一接收入口（设置超时）
    @Override
    public SocketResult ServerSocket_INPUT(String receiveType) throws IOException {
        if (server == null || server.isClosed()) {
            return new SocketResult(false, "ServerSocket未启动", null);
        }

        // 初始化连接并设置超时
        if (clientSocket == null || clientSocket.isClosed()) {
            clientSocket = server.accept();
            clientSocket.setSoTimeout(TIMEOUT_MS); // 关键：设置5秒超时
            this.dis = new DataInputStream(clientSocket.getInputStream());
            this.dos = new DataOutputStream(clientSocket.getOutputStream());
            System.out.println("客户端连接成功，开始接收数据（类型：" + receiveType + "），超时设置为5秒");
        } else {
            System.out.println("复用已有连接，接收数据（类型：" + receiveType + "）");
        }

        // 根据类型调用对应接收方法
        if ("STRING".equals(receiveType)) {
            return ServerSocket_INPUT_STRING();
        } else if ("FILE".equals(receiveType)) {
            return ServerSocket_INPUT_FILE();
        } else {
            return new SocketResult(false, "未知接收类型：" + receiveType, null);
        }
    }


    // 5. 基础输出方法
    @Override
    public boolean ServerSocket_OUTPUT() throws IOException {
        if (clientSocket == null || clientSocket.isClosed()) {
            clientSocket = server.accept();
            clientSocket.setSoTimeout(TIMEOUT_MS); // 设置超时
        }
        this.dos = new DataOutputStream(clientSocket.getOutputStream());
        dos.writeUTF("服务器已接收到请求");
        dos.flush();
        return true;
    }


    // 6. 关闭服务器
    @Override
    public boolean ServerSocket_CLOSE() throws IOException {
        if (dis != null) dis.close();
        if (dos != null) dos.close();
        if (clientSocket != null && !clientSocket.isClosed()) {
            clientSocket.close();
            System.out.println("客户端连接已关闭（超时或主动关闭）");
        }
        if (server != null && !server.isClosed()) server.close();
        System.out.println("ServerSocket及资源已关闭");
        return true;
    }


    // 7. 创建输出专用Socket
    @Override
    public boolean ServerSocket_OUTPUT_CREATE_Socket() throws IOException {
        if (server == null || server.isClosed()) {
            return ServerSocket_CREATE_Socket();
        }
        if (clientSocket == null || clientSocket.isClosed()) {
            clientSocket = server.accept();
            clientSocket.setSoTimeout(TIMEOUT_MS); // 设置超时
        }
        this.dos = new DataOutputStream(clientSocket.getOutputStream());
        return true;
    }


    // 8. 输出字符串
    @Override
    public SocketResult ServerSocket_OUTPUT_OUTPUT_String() throws IOException {
        if (dos == null) {
            return new SocketResult(false, "输出流未初始化", null);
        }
        try {
            String data = "默认输出字符串（可由Medium结果填充）";
            dos.writeUTF(data);
            dos.flush();
            return new SocketResult(true, "字符串输出成功", data);
        } catch (IOException e) {
            return new SocketResult(false, "字符串输出失败：" + e.getMessage(), null);
        }
    }


    // 9. 输出长文本
    @Override
    public boolean ServerSocket_OUTPUT_OUTPUT_String_langege() throws IOException {
        if (dos == null) return false;
        try {
            String longText = "这是一段长文本...".repeat(500);
            dos.writeUTF("LONG_TEXT");
            dos.writeUTF(longText);
            dos.flush();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }


    // 10. 输出文件（下载）
    @Override
    public boolean ServerSocket_OUTPUT_OUTPUT_download() throws IOException {
        if (dos == null) return false;
        try {
            String fileName = "test_download.txt";
            File file = new File(baseTxtPath + fileName);
            if (!file.exists()) {
                System.out.println("文件不存在！路径：" + file.getAbsolutePath());
                return false;
            }
            dos.writeUTF("FILE");
            dos.writeUTF(fileName);
            dos.writeLong(file.length());
            dos.write(Files.readAllBytes(file.toPath()));
            dos.flush();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }


    // 11. 统一输出入口
    @Override
    public SocketResult ServerSocket_OUTPUT_OUTPUT() throws IOException {
        if (!ServerSocket_OUTPUT_CREATE_Socket()) {
            return new SocketResult(false, "输出连接创建失败", null);
        }
        SocketResult result = ServerSocket_OUTPUT_OUTPUT_String();
        return result;
    }


    // 12. 接收输出响应（添加超时处理）
    @Override
    public boolean ServerSocket_OUTPUT_INPUT() throws IOException {
        if (dis == null) {
            this.dis = new DataInputStream(clientSocket.getInputStream());
        }
        try {
            String response = dis.readUTF();
            return "SUCCESS".equals(response);
        } catch (SocketTimeoutException e) {
            ServerSocket_CLOSE();
            throw new IOException("接收响应超时（5秒），已断开连接", e);
        }
    }


    // 13. 关闭输出连接
    @Override
    public boolean ServerSocket_OUTPUT_CLOSE() throws IOException {
        if (dos != null) dos.close();
        if (clientSocket != null && !clientSocket.isClosed()) clientSocket.close();
        return true;
    }


    // 14. 接收用户ID（添加超时处理）
    @Override
    public SocketResult ServerSocket_INPUT_USERID() throws IOException {
        if (dis == null) {
            return new SocketResult(false, "输入流未初始化", null);
        }
        try {
            String userId = dis.readUTF();
            System.out.println("收到用户ID：" + userId);
            String authMsg = "AUTH_SUCCESS: " + userId + " 有权限访问";
            dos.writeUTF(authMsg);
            dos.flush();
            System.out.println("已发送权限校验结果：" + authMsg);
            return new SocketResult(true, "用户ID接收成功", userId);
        } catch (SocketTimeoutException e) {
            ServerSocket_CLOSE();
            return new SocketResult(false, "接收用户ID超时（5秒），已断开连接", null);
        } catch (IOException e) {
            return new SocketResult(false, "用户ID接收失败：" + e.getMessage(), null);
        }
    }


    // 15. 输出权限校验结果
    @Override
    public SocketResult ServerSocket_OUTPUT_USER_AUTH(String authMsg) throws IOException {
        if (dos == null) {
            return new SocketResult(false, "输出流未初始化", null);
        }
        try {
            dos.writeUTF(authMsg);
            dos.flush();
            return new SocketResult(true, "权限校验结果输出成功", authMsg);
        } catch (IOException e) {
            return new SocketResult(false, "权限校验结果输出失败：" + e.getMessage(), null);
        }
    }
}